#include <armadillo>
#include "Density.hpp" 
#include "utils.hpp"
#include <cmath>
#include "Gibbs.hpp"

//#define _C 0.9
#define _U 0.9


using namespace arma;
//Pass W as mat type
//change Weight and Resample accordingly
// Check sizes
// template specialization: if Density is a IBIS an implementation
// and if a tempering a diffrent one

#define _P 20 

template<class Kernel, class Resample, class Density>
class Particle{
	///////////////////////////////////////////
	public:
	Particle(Kernel *K,Resample *R,Density *D,int M){
		_p=(*D).Get_p();
		mat Xt(M,_p);//p le nombre de parametre a obtenir de Density
		double *Wt=new double[M];
		X=Xt;
		_K=K;
		_R=R;
		_D=D;
		W=Wt;
		thres=_U*M;
		this->Normalize();
		_M=M;
		y=X.t();
		_n=(*D).Get_n();
	//	cout << "///" << _n << "///";
	}
	~Particle(){
		delete[] W;
	}
	void Step(int i)
	{
	
	}
	double Ess_W(void)//renormalisation???
	{
		double *foo= new double[_M];
		double sum=0;

		for(int i=0;i<_M;i++)
		{
			sum+=W[i];
		}
		_Z=sum;
		for(int j=0;j<_M;j++)
		{
			foo[j]=(W[j]/sum);
		}

		sum=0;
		for(int i=0;i<_M;i++)
		{
			sum+=foo[i]*foo[i];
		}
		delete[] foo;

		return 1/sum;		
	}
	void Init()
	{
		
	}
	
	void Filter(void){}

	mat Get_theta(void){
		return X;
	}

	void Normalize(void){
		for(int i=0;i<_M;i++){W[i]=1;}
	}
	double* Get_W(void)
	{
		return W;
	}

	////////////////////////////////////////////
	private:
	mat X;//value particle
	double *W;//weigths
	double Ess;
	int _M;
	double thres;
	double _Z;
	Kernel *_K;
	Resample *_R;
	Density *_D;	
	mat y;
	int _n;
	int _p;
};

#include "IBIS.hpp"
#include "Tempering.hpp"
#include "GeomBridge.hpp"


